package com.tomek.ktoryoperator.providers;

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import android.content.Context;

import com.tomek.ktoryoperator.R;
import com.tomek.ktoryoperator.exceptions.NumberInfoProviderException;
import com.tomek.ktoryoperator.model.NetworkType;
import com.tomek.ktoryoperator.utils.DateUtils;
import com.tomek.ktoryoperator.utils.TelephonyUtils;

public abstract class AbstractEraNerNumberInfoProvider extends AbstractPolishNumberInfoProvider {
	private static final int TIMEOUT = 8000;

	// private static final String[] MOBILE_PREFIXES = new String[] { "50", "51", "53", "60", "66", "69", "72", "78",
	// "79", "88" };

	// private static final HashSet<String> MOBILE_PREFIXES_SET = new HashSet<String>(Arrays.asList(MOBILE_PREFIXES));

	private static final long AFTER_ACCESS_DENIED_INTERVAL = 1000 * 60 * 30; // 30 minutes
	private static final long REQUERY_TIMEOUT = DateUtils.DAY_MS;

	private static Pattern HTML_PATTERN = Pattern
			.compile("<b>Kod sieci:</b></td><td>(\\d\\d\\d \\d\\d)</td>.*Operator:</b></td><td>(.+)</td>");

	private long lastAccessDeniedTimestamp = 0;

	@Override
	public long getQueryTimeout() {
		return REQUERY_TIMEOUT;
	}

	@Override
	public String getNumberInfoId(String number) throws NumberInfoProviderException {
		if (System.currentTimeMillis() - lastAccessDeniedTimestamp < AFTER_ACCESS_DENIED_INTERVAL) {
			throw new NumberInfoProviderException(R.string.access_deny_delay);
		}

		return readOperator(number);
	}

	public String readOperator(String number) throws NumberInfoProviderException {
		HttpParams my_httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(my_httpParams, TIMEOUT);
		HttpConnectionParams.setSoTimeout(my_httpParams, TIMEOUT);

		HttpClient client = new DefaultHttpClient(my_httpParams);

		try {
			String req = getServiceUrl() + TelephonyUtils.trimLeadingPlus(number);

			ResponseHandler<String> responseHandler = new BasicResponseHandler();
			String text = client.execute(new HttpGet(req), responseHandler);

			if (text.indexOf("Brak danych") >= 0) {
				return null;
			} else if (text.indexOf("Access denied") >= 0) {
				lastAccessDeniedTimestamp = System.currentTimeMillis();

				throw new NumberInfoProviderException(R.string.read_error_access_denied);
			} else {
				NetworkType nt = getNetwork(text);
				return nt != null ? nt.toString() : null;
			}
		} catch (ClientProtocolException e1) {
			throw new NumberInfoProviderException(R.string.read_error_network_error);
		} catch (IOException e1) {
			throw new NumberInfoProviderException(R.string.read_error_network_error);
		}
	}

	private NetworkType getNetwork(String rawData) {
		NetworkType ret = null;

		Matcher matcher = HTML_PATTERN.matcher(rawData);

		while (matcher.find() && matcher.groupCount() > 0) {
			String kod = matcher.group(1);
			ret = getNetworkInternal(kod);

			if (ret == NetworkType.ERA) {
				String kod2 = matcher.group(2);
				ret = getNetworkInternalEra(kod2);
			}
		}

		return ret;
	}

	static NetworkType getNetworkInternal(String symbol) {
		if (symbol.endsWith("01")) {
			return NetworkType.PLUS;
		}

		if (symbol.endsWith("02")) {
			return NetworkType.ERA;
		}

		if (symbol.endsWith("03") || symbol.endsWith("05")) {
			return NetworkType.ORANGE;
		}

		if (symbol.endsWith("06")) {
			return NetworkType.PLAY_P4;
		}

		if (symbol.endsWith("07")) {
			return NetworkType.NETIA;
		}

		if (symbol.endsWith("08")) {
			return NetworkType.ETELKO;
		}

		if (symbol.endsWith("09")) {
			return NetworkType.TK_TELEKOM;
		}

		if (symbol.endsWith("10") || symbol.endsWith("13") || symbol.endsWith("14")) {
			return NetworkType.SFERIA;
		}

		if (symbol.endsWith("11")) {
			return NetworkType.NORDISK;
		}

		if (symbol.endsWith("12")) {
			return NetworkType.CYFROWY_POLSAT;
		}

		if (symbol.endsWith("15")) {
			return NetworkType.CENTERNET_WRODZINIE;
		}

		if (symbol.endsWith("16")) {
			return NetworkType.MOBYLAND;
		}

		if (symbol.endsWith("17")) {
			return NetworkType.AERO2;
		}

		return null;
	}

	private NetworkType getNetworkInternalEra(String kod2) {
		if (kod2.equals("Heyah")) {
			return NetworkType.ERA_HEYAH;
		} else if (kod2.equals("MEC A.S.")) {
			return NetworkType.ERA_MOBILKING;
		} else if (kod2.equals("tuBiedronka")) {
			return NetworkType.ERA_BIEDRONKA;
		}

		return NetworkType.ERA;
	}

	@Override
	public int getImageResourceForNumber(String networkType) {
		if (networkType == null) {
			return android.R.drawable.ic_menu_help;
		}

		if (networkType.equals("ERA")) {
			return R.drawable.operator_pl_era2;
		} else if (networkType.equals("HEYAH")) {
			return R.drawable.operator_pl_heyah2;
		} else if (networkType.equals("MOBILKING")) {
			return R.drawable.operator_pl_mobilking2;
		} else if (networkType.equals("BIEDRONKA")) {
			return R.drawable.operator_pl_biedronka2;
		} else if (networkType.equals("PLUS")) {
			return R.drawable.operator_pl_plus;
		} else if (networkType.equals("PLAY")) {
			return R.drawable.operator_pl_play;
		} else if (networkType.equals("ORANGE")) {
			return R.drawable.operator_pl_orange;
		} else if (networkType.equals("W RODZINIE")) {
			return R.drawable.operator_pl_wrodzinie2;
		} else if (networkType.equals("CYFROWY POLSAT")) {
			return R.drawable.operator_pl_cyfrowy_polsat;
		} else if (networkType.equals("SFERIA")) {
			return R.drawable.operator_pl_sferia;
		} else if (networkType.equals("MOBYLAND")) {
			return R.drawable.operator_pl_mobyland;
		} else if (networkType.equals("NETIA")) {
			return R.drawable.operator_pl_netia;
		} else if (networkType.equals("AERO2")) {
			return R.drawable.operator_pl_aero2;
		} else if (networkType.equals("TK_TELEKOM")) {
			return R.drawable.operator_pl_tktelekom;
		} else if (networkType.equals("ETELKO")) {
			return R.drawable.operator_pl_etelko;
		} else if (networkType.equals("NORDISK")) {
			return R.drawable.operator_pl_nordisk;

		} else if (networkType.equals("STACJONARNY")) {
			return R.drawable.ic_phone;
		} else {
			return 0;
		}
	}

	@Override
	public String getNumberInfoName(Context context, String numberInfoId) {
		return numberInfoId;
	}

	protected abstract String getServiceUrl();
}